package com.advertisementsystem.Servie.Impl;

import com.advertisementsystem.Dto.LoginUser;
import com.advertisementsystem.Dto.NegotiationDTO;
import com.advertisementsystem.Dto.NegotiationQueryDTO;
import com.advertisementsystem.Dto.TimeSlot;
import com.advertisementsystem.Exception.BusinessException;
import com.advertisementsystem.Mapper.AdNegotiationMapper;
import com.advertisementsystem.Mapper.AdScheduleMapper;
import com.advertisementsystem.Mapper.AdvertisementMapper;
import com.advertisementsystem.Mapper.UserMapper;
import com.advertisementsystem.Servie.*;
import com.advertisementsystem.entity.AdNegotiation;
import com.advertisementsystem.entity.Advertisement;
import com.advertisementsystem.entity.Schedule;
import com.advertisementsystem.entity.User;
import com.advertisementsystem.vo.NegotiationVO;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class NegotiationServiceImpl implements NegotiationService {

    @Autowired
    private AdNegotiationMapper negotiationMapper;

    @Autowired
    private AdvertisementService advertisementService;

    @Autowired
    private UserService userService;

    @Autowired
    private AdScheduleMapper adScheduleMapper;

    @Autowired
    private AdvertisementMapper advertisementMapper;

    @Autowired
    private BillService billService;

    @Autowired
    private NotificationService notificationService;
    @Override
    public void createNegotiation(NegotiationDTO dto) {
        // 获取当前用户
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();

        // 验证广告
        Advertisement ad = advertisementService.getAdvertisementDetail(dto.getAdId());
        if (ad == null) {
            throw new BusinessException("广告不存在");
        }

        if (dto.getTimeSlots()==null)
        {
            List<TimeSlot> timeSlots = new ArrayList<>();
            TimeSlot timeSlot = new TimeSlot();
            timeSlot.setStartTime("00:00");
            timeSlot.setEndTime("23:59");
            timeSlots.add(timeSlot);
            dto.setTimeSlots(timeSlots);
        }

        // 创建协商记录
        AdNegotiation negotiation = new AdNegotiation();
        negotiation.setAdId(dto.getAdId());
        negotiation.setAdvertiserId(ad.getAdvertiserId());
        negotiation.setDeviceOwnerId(loginUser.getUser().getId());
        negotiation.setContent(dto.getContent());
        negotiation.setPrice(dto.getPrice());
        negotiation.setTimeSlots(dto.getTimeSlots());
        negotiation.setStatus(0);
        negotiation.setCreatedTime(LocalDateTime.now());
        negotiation.setUpdatedTime(LocalDateTime.now());
        negotiation.setDeviceId(dto.getDeviceId());


        negotiationMapper.insert(negotiation);
    }

    @Override
    public IPage<NegotiationVO> getNegotiationList(Integer pageNum, Integer pageSize,
                                                   String adname, Long deviceId, String status) {
        // 获取当前用户
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();

        // 构建查询条件
        Page<AdNegotiation> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<AdNegotiation> wrapper = new LambdaQueryWrapper<>();


        if (deviceId!=null)
        {
            wrapper.eq(AdNegotiation::getDeviceId, deviceId);
        }
        if(status!=null)
        {
            wrapper.eq(AdNegotiation::getStatus, Integer.parseInt(status));
        }

        // 根据角色设置查询条件
        if (loginUser.getPermissions().contains("ROLE_ADVERTISER")) {
            wrapper.eq(AdNegotiation::getAdvertiserId, loginUser.getUser().getId());
        } else if (loginUser.getPermissions().contains("ROLE_DEVICE_OWNER")) {
            wrapper.eq(AdNegotiation::getDeviceOwnerId, loginUser.getUser().getId());
        }

        wrapper.orderByDesc(AdNegotiation::getCreatedTime);

        // 执行查询
        Page<AdNegotiation> result = negotiationMapper.selectPage(page, wrapper);

        // 转换为VO
        return convertToVOPage(result,adname);
    }

    @Override
    public void completeNegotiation(Long id) {
        // 获取当前用户
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();

        // 验证协商记录
        AdNegotiation negotiation = negotiationMapper.selectById(id);
        if (negotiation == null) {
            throw new BusinessException("协商记录不存在");
        }

        // 验证权限
        if (!negotiation.getAdvertiserId().equals(loginUser.getUser().getId()) &&
                !negotiation.getDeviceOwnerId().equals(loginUser.getUser().getId())) {
            throw new BusinessException("无权操作此协商记录");
        }

        // 更新状态
        negotiation.setStatus(1);
        negotiation.setUpdatedTime(LocalDateTime.now());
        negotiationMapper.updateById(negotiation);

        // 更新广告投放计划
        List<TimeSlot> timeSlots =negotiation.getTimeSlots();
        // TODO: 更新投放计划的时段和价格
        LambdaQueryWrapper<Schedule> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Schedule::getAdvertisementId, negotiation.getAdId());
        wrapper.eq(Schedule::getDeviceId, negotiation.getDeviceOwnerId());
        wrapper.eq(Schedule::getStatus, "PENDING");
        Schedule schedule = adScheduleMapper.selectOne(wrapper);
        schedule.setTimeSlots(timeSlots);
        adScheduleMapper.updateById(schedule);
        log.info("Updated schedule: {}", schedule.getId());
        LambdaUpdateWrapper<Advertisement> UpdateWrapper = new LambdaUpdateWrapper<>();
        UpdateWrapper.eq(Advertisement::getId, negotiation.getAdId());
        UpdateWrapper.set(Advertisement::getBudget, negotiation.getPrice());
        advertisementMapper.update(null, UpdateWrapper);

        // 生成账单
        billService.createBill(id);

        User currentUser = userService.getUserById(loginUser.getUser().getId());
        notificationService.createNegotiationCompletedNotification(
                negotiation.getId(),
                negotiation.getAdId(),
                negotiation.getAdvertiserId(),
                currentUser.getNickname());

    }

    @Override
    public void cancelNegotiation(Long id) {
        // 获取当前用户
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();

        // 验证协商记录
        AdNegotiation negotiation = negotiationMapper.selectById(id);
        if (negotiation == null) {
            throw new BusinessException("协商记录不存在");
        }

        // 验证权限
        if (!negotiation.getAdvertiserId().equals(loginUser.getUser().getId()) &&
                !negotiation.getDeviceOwnerId().equals(loginUser.getUser().getId())) {
            throw new BusinessException("无权取消此协商记录");
        }

        // 验证状态
        if (negotiation.getStatus() != 0) {
            throw new BusinessException("只能取消进行中的协商");
        }

        // 更新状态为已取消
        negotiation.setStatus(2);
        negotiation.setUpdatedTime(LocalDateTime.now());
        negotiationMapper.updateById(negotiation);

        log.info("Cancelled negotiation: {}, by user: {}", id, loginUser.getUser().getId());
    }

    @Override
    public void updateNegotiation(Long id, NegotiationDTO dto) {
        // 获取当前用户
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();

        // 验证协商记录是否存在
        AdNegotiation negotiation = negotiationMapper.selectById(id);
        if (negotiation == null) {
            throw new BusinessException("协商记录不存在");
        }

        // 验证权限
        if (!negotiation.getAdvertiserId().equals(loginUser.getUser().getId()) &&
                !negotiation.getDeviceOwnerId().equals(loginUser.getUser().getId())) {
            throw new BusinessException("无权更新此协商记录");
        }

        // 验证协商状态
        if (negotiation.getStatus() != 0) {
            throw new BusinessException("只能更新进行中的协商");
        }

        // 更新协商内容
        negotiation.setPrice(dto.getPrice());
        negotiation.setTimeSlots(dto.getTimeSlots());
        negotiation.setContent(dto.getContent());
        negotiation.setUpdatedTime(LocalDateTime.now());

        negotiationMapper.updateById(negotiation);

        log.info("Updated negotiation: {}, by user: {}", id, loginUser.getUser().getId());
    }

    @Override
    public NegotiationVO getNegotiationDetail(Long id) {
        // 获取当前用户
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();

        // 查询协商记录
        AdNegotiation negotiation = negotiationMapper.selectById(id);
        log.info("Get negotiation detail: {}", negotiation);
        if (negotiation == null) {
            throw new BusinessException("协商记录不存在");
        }

        log.info("当前用户id{}",loginUser.getUser().getId());
        // 验证查看权限
        if (!negotiation.getAdvertiserId().equals(loginUser.getUser().getId()) &&
                !negotiation.getDeviceOwnerId().equals(loginUser.getUser().getId()) &&
                !loginUser.getPermissions().contains("ROLE_ADMIN")) {
            throw new BusinessException("无权查看此协商记录");
        }

        // 转换为VO
        NegotiationVO vo = new NegotiationVO();
        vo.setDeviceId(negotiation.getDeviceId());
        BeanUtils.copyProperties(negotiation, vo);

        // 设置广告信息
        Advertisement ad = advertisementService.getAdvertisementDetail(negotiation.getAdId());
        if (ad != null) {
            vo.setAdvertisementName(ad.getTitle());
        }

        // 设置用户信息
        User advertiser = userService.getUserById(negotiation.getAdvertiserId());
        User deviceOwner = userService.getUserById(negotiation.getDeviceOwnerId());
        vo.setAdvertiserUserId(negotiation.getAdvertiserId());
        vo.setDeviceOwnerUserId(negotiation.getDeviceOwnerId());
        vo.setAdvertiserName(advertiser != null ? advertiser.getUsername() : "");
        vo.setDeviceOwnerName(deviceOwner != null ? deviceOwner.getUsername() : "");

        if (negotiation.getTimeSlots()!=null)
        {
            vo.setTimeSlots(negotiation.getTimeSlots());
        }
        // 转换时段


        return vo;
    }

    private IPage<NegotiationVO> convertToVOPage(Page<AdNegotiation> page, String adname) {
        Page<NegotiationVO> voPage = new Page<>();
        BeanUtils.copyProperties(page, voPage, "records");

        List<NegotiationVO> voList = new ArrayList<>();

        for (AdNegotiation negotiation : page.getRecords()) {
            // 获取广告信息
            Advertisement ad = advertisementService.getAdvertisementDetail(negotiation.getAdId());

            // 如果adname不为空，进行模糊匹配过滤
            if (adname != null && !adname.isEmpty() && ad != null) {
                // 如果广告标题不包含搜索关键词，跳过此记录
                if (!ad.getTitle().toLowerCase().contains(adname.toLowerCase())) {
                    continue;
                }
            }

            NegotiationVO vo = new NegotiationVO();
            BeanUtils.copyProperties(negotiation, vo);

            // 设置广告名称
            if (ad != null) {
                vo.setAdvertisementName(ad.getTitle());
            }

            // 设置用户名称
            User advertiser = userService.getUserById(negotiation.getAdvertiserId());
            User deviceOwner = userService.getUserById(negotiation.getDeviceOwnerId());
            vo.setAdvertiserName(advertiser != null ? advertiser.getUsername() : "");
            vo.setDeviceOwnerName(deviceOwner != null ? deviceOwner.getUsername() : "");

            // 转换时段
            vo.setTimeSlots(negotiation.getTimeSlots());

            voList.add(vo);
        }

        // 由于我们可能筛选掉了一些记录，需要更新total值
        voPage.setRecords(voList);
        voPage.setTotal(voList.size());

        return voPage;
    }
}